package com.chengzheng.crawler.spiderman.work;

import com.chengzheng.crawler.spiderman.pojo.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author zhengcheng
 * @date 2018/1/30
 * @time 下午5:41
 * @email chengzhengzheng@meituan.com
 **/

public abstract class Worker extends Thread {


    private final String childClassName;

    private static final Logger LOGGER = LoggerFactory.getLogger(Worker.class);

    private boolean stop = false;

    private WorkerManager manager;

    public Worker(WorkerManager manager) {
        this.manager = manager;
        this.childClassName = getClass().getName();
    }


    protected WorkerManager getManager() {
        return this.manager;
    }

    @Override
    public void run() {

        while (true) {
            if (this.stop || this.isInterrupted()) {
                return;
            }

            final Task task;
            try {
                task = manager.takeTask();
            } catch (Exception e) {
                LOGGER.error("[" + this.childClassName + "]Failed to take task from manager!", e);
                continue;
            }

            if (task == null) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    setStopState(true);
                }
                continue;
            }

            LOGGER.info("[" + this.childClassName + "]" + this.getName() + " 获取任务: " + task);

            try {
                this.work(task);
            } catch (Exception e) {
                LOGGER.error("[" + this.childClassName + "]" + this.getName() + " 任务失败: " + task, e);
                continue;
            }
            LOGGER.info("[" + this.childClassName + "]" + this.getName() + " 完成任务: " + task);
        }
    }


    /**
     * 获取线程具体线程名称
     *
     * @return
     */
    public abstract String getThreadName();

    /**
     * 开始工作
     *
     * @param task
     */
    protected abstract void work(Task task);

    protected void setStopState(boolean stopState) {
        this.stop = stopState;
    }
}
